﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using Orion.Models;
using Orion.MyLib;

namespace Orion.Controllers
{
	[HandleError]
    public class AccountController : Controller
    {
    	private UserRepository m_userRep = new UserRepository();

        public IFormsAuthenticationService FormsService { get; set; }
        public IMembershipService MembershipService { get; set; }

        protected override void Initialize(RequestContext requestContext)
        {
            if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
            if (MembershipService == null) { MembershipService = new AccountMembershipService(); }

            base.Initialize(requestContext);
        }

        // **************************************
        // URL: /Account/LogOn
        // **************************************

        public ActionResult LogOn()
        {
            return View();
        }

        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ValidateUser(model.UserName, model.Password))
                {
                    FormsService.SignIn(model.UserName, model.RememberMe);
                    if (Url.IsLocalUrl(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Work");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "Notendanafn eða lykilorð er ekki rétt.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        // **************************************
        // URL: /Account/LogOff
        // **************************************

        public ActionResult LogOff()
        {
            FormsService.SignOut();

            return RedirectToAction("Index", "Home");
        }

        // **************************************
        // URL: /Account/Register
        // **************************************

		[ Authorize ( Roles = "Admin" ) ]
        public ActionResult Register( )
        {
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View();
        }

		[Authorize(Roles = "Admin")]
        [HttpPost]
		public ActionResult Register(RegisterModel model, HttpPostedFileBase file, string role)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);

                if (createStatus == MembershipCreateStatus.Success)
                {
					if ( ! Roles.IsUserInRole(model.UserName, role ) )
					{

						if (model.User.Valid != false)
						{
							Roles.AddUserToRole(model.UserName, role);
						}
						
					}
					

					//input data into custom User
					MembershipUser newUser = Membership.GetUser(model.UserName);
                	model.User.UserID = (Guid)newUser.ProviderUserKey;
                	model.User.Valid = true;

					
					if (file != null && file.ContentLength > 0)
					{
						var folder = Path.Combine(Server.MapPath("~/Content/UserMyndir"));
						var fileEnding = file.FileName.Split('.');
						var path = Path.Combine(Server.MapPath("~/Content/UserMyndir"), model.User.UserID + "." + fileEnding[1]);

						//validate folder exist
						if (!Directory.Exists(folder))
						{
							Directory.CreateDirectory(folder);
						}

						file.SaveAs(path);
						model.User.Picture = string.Format("/Content/UserMyndir/{0}.{1}" , model.User.UserID, fileEnding[1] );
					}

                	CreateUser(model.User);
                    return RedirectToAction("Index", "Work");
                }
                else
                {
                    ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
                }
            }

            // If we got this far, something failed, redisplay form
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View(model);
        }

        // **************************************
        // URL: /Account/ChangePassword
        // **************************************

        [Authorize]
        public ActionResult ChangePassword()
        {
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult ChangePassword(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
                {
                    return RedirectToAction("ChangePasswordSuccess");
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                }
            }

            // If we got this far, something failed, redisplay form
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View(model);
        }

        // **************************************
        // URL: /Account/ChangePasswordSuccess
        // **************************************

        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

		[HttpPost]
		public ActionResult CreateUser( User u )
		{
			try
			{
				//validation
				if ( ModelState.IsValid )
				{
					var userRep = new UserRepository( );

					userRep.AddUser(u);
				}

				return RedirectToAction( "Index" );
			}
			catch ( Exception ex )
			{
				var log = new Logger( );
				log.LogExcepion( ex );
				return View( "Error" );
			}
			
		}

		public ActionResult Edit( int? id )
		{
			try
			{
				//validation
				if (!id.HasValue)
				{
					RedirectToAction("Index", "Home");
				}

				var model = m_userRep.GetUserById(id.Value);

				return View(model);
			}
			catch ( Exception ex )
			{
				var log = new Logger();
				log.LogExcepion(ex);
				return View( "Error" );
			}
			
		}

		[HttpPost]
		public ActionResult Edit(FormCollection form, HttpPostedFileBase file, string role )
		{
			try
			{
				//validation
				if ( ! ModelState.IsValid )
				{
					return View( form );
				}

				var user = new User();
				UpdateModel(user);

				//ID is returned as string, for some reason need to change it back to int for use.
				int temp;
				if (!int.TryParse(form["ID"], out temp))
				{
					throw new Exception("ID af notanda tapaðist við tilraun til þess að breyta henni");
				}

				user.ID = temp;
				//get old instance of user as for some reason I can't access user.aspnt_User.UserName from
				//current instance of user and as I do not make it optinal to change username anyway it is
				//is allowed even thou shorter way would be preferable.

				//if user is not admin he cannot change his role
				if( User.IsInRole("Admin" ))
				{
					var userrep = new UserRepository();
					var newuser = userrep.GetUserById(user.ID);
					var name = newuser.aspnet_User.UserName;

					//get all roles for currnet system
					var roles = Roles.GetAllRoles();
					//remove user from all roles he is in
					foreach (var r in roles)
					{
						if (Roles.IsUserInRole(name, r))
						{
							Roles.RemoveUserFromRole(name, r);
						}

					}
					//if user is actvie he then get assigned his ( maybe changed ) role back
					if (user.Valid != false)
					{
						Roles.AddUserToRole(name, role);
					}
				}
				

				//check if file has been submited
				if ( file != null && file.ContentLength > 0 )
				{
					//file saved to hard drive and relative path from web aplication saved
					var fileEnding = file.FileName.Split( '.' );
					var folder = Path.Combine(Server.MapPath( "~/Content/UserMyndir" ) );
					var path = Path.Combine(Server.MapPath("~/Content/UserMyndir"), user.UserID + "." + fileEnding[1]);

					//validate folder exist if not it is created
					if (!Directory.Exists(folder))
					{
						Directory.CreateDirectory(folder);
					}
					
					file.SaveAs(path);
					user.Picture = string.Format("/Content/UserMyndir/{0}.{1}", user.UserID, fileEnding[1] );
				}

				m_userRep.UpdateUser(user);

				return RedirectToAction("Index", "Work");
			}
			catch ( Exception ex )
			{
				var log = new Logger( );
				log.LogExcepion( ex );
				return View( "Error" );
			}
			
		}
		[Authorize]
		public ActionResult GetCurrentUser( )
		{
			try
			{
				//allir notendur sóttir og innskráður notendi skilað til baka.
				var temp = m_userRep.GetAllUsers();
				var model = (from t in temp
							 where User.Identity.Name == t.aspnet_User.UserName
							 select t).SingleOrDefault();

				return View("Edit", model);
			}
			catch ( Exception ex )
			{
				var log = new Logger( );
				log.LogExcepion( ex );
				return View( "Error" );
			}
			
		}

		public ActionResult GetAllUsers( int? id )
		{
			//validate input
			if ( ! id.HasValue )
			{
				return RedirectToAction("Index");
			}

			var model = m_userRep.GetAllUsers(id.Value);

			return View(model);
		}
    }
}
